<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import { getAllCity } from '@/api/shops'
import storage from '@/utils/storage'

const props = defineProps({
  idKey: {
    type: String,
    default: 'id',
  },
  rangeKey: {
    type: String,
    default: 'name',
  },
  title: {
    type: String,
    default: '',
  },
  multiple: { // 是否可以多选
    type: Boolean,
    default: true,
  },
  selectParent: { // 是否可以选父级
    type: Boolean,
    default: true,
  },
  foldAll: { // 折叠时关闭所有已经打开的子集，再次打开时需要一级一级打开
    type: Boolean,
    default: true,
  },
  confirmColor: { // 确定按钮颜色
    type: String,
    default: '', // #07bb07
  },
  cancelColor: { // 取消按钮颜色
    type: String,
    default: '', // #757575
  },
  titleColor: { // 标题颜色
    type: String,
    default: '', // #757575
  },
  currentIcon: { // 展开时候的ic
    type: String,
    default: '',
  },
  defaultIcon: { // 折叠时候的ic
    type: String,
    default: '',
  },
  lastIcon: { // 没有子集的ic
    type: String,
    default: '',
  },
  border: { // 是否有分割线
    type: Boolean,
    default: false,
  },
})

const emit = defineEmits(['range', 'cancel', 'selected'])

const range = ref([])
const showTree = ref(false)
const treeList = ref([])
const selectIndex = ref(-1)

watch(() => props.multiple, (first, second) => {
  if (range.value.length)
    _reTreeList()
})

watch(() => props.selectParent, (first, second) => {
  if (range.value.length)
    _reTreeList()
})

onMounted(() => {
  init()
  _initTree()
})

function init() {
  getAllCity().then((res) => {
    if (res.data.success) {
      range.value = res.data.result
      emit('range', range.value)
    }
  })
}

function _show() {
  showTree.value = true
}

function _hide() {
  showTree.value = false
}

function _cancel() {
  _hide()
  emit('cancel', '')
}

function _confirm() {
  // 处理所选数据
  const rt = []
  let obj = {}
  treeList.value.forEach((v, i) => {
    if (treeList.value[i].checked) {
      obj = {}
      obj.parents = treeList.value[i].parents
      obj = Object.assign(obj, treeList.value[i].source)
      // 移除子元素
      delete obj.children
      rt.push(obj)
    }
  })
  emit('selected', rt)
  _hide()
}

// 扁平化树结构
function _renderTreeList(list = [], rank = 0, parentId = [], parents = []) {
  list.forEach((item) => {
    treeList.value.push({
      id: item[props.idKey],
      name: item[props.rangeKey],
      source: item,
      parentId, // 父级id数组
      parents, // 父级id数组
      rank, // 层级
      showChild: false, // 子级是否显示
      open: false, // 是否打开
      show: rank === 0, // 自身是否显示
      hideArr: [],
      orChecked: item.checked ? item.checked : false,
      checked: item.checked ? item.checked : false,
    })
    if (Array.isArray(item.children) && item.children.length > 0) {
      // console.log(item)
      const parentid = [...parentId]
      const parentArr = [...parents]
      const childrenid = [...childrenid]
      delete parentArr.children
      parentid.push(item[props.idKey])
      parentArr.push({
        [props.idKey]: item[props.idKey],
        [props.rangeKey]: item[props.rangeKey],
      })
      _renderTreeList(item.children, rank + 1, parentid, parentArr)
    }
    else {
      treeList.value[treeList.value.length - 1].lastRank = true
    }
  })
}

export default {
  name: 'TkiTree',
  methods: {
    // 扁平化树结构
    _renderTreeList(list = [], rank = 0, parentId = [], parents = []) {
      list.forEach((item) => {
        this.treeList.push({
          id: item[this.idKey],
          name: item[this.rangeKey],
          source: item,
          parentId, // 父级id数组
          parents, // 父级id数组
          rank, // 层级
          showChild: false, // 子级是否显示
          open: false, // 是否打开
          show: rank === 0, // 自身是否显示
          hideArr: [],
          orChecked: item.checked ? item.checked : false,
          checked: item.checked ? item.checked : false,
        })
        if (Array.isArray(item.children) && item.children.length > 0) {
          // console.log(item)
          const parentid = [...parentId]
          const parentArr = [...parents]
          const childrenid = [...childrenid]
          delete parentArr.children
          parentid.push(item[this.idKey])
          parentArr.push({
            [this.idKey]: item[this.idKey],
            [this.rangeKey]: item[this.rangeKey],
          })
          this._renderTreeList(item.children, rank + 1, parentid, parentArr)
        }
        else {
          this.treeList[this.treeList.length - 1].lastRank = true
        }
      })
    },
    // 处理默认选择
    _defaultSelect() {
      this.treeList.forEach((v, i) => {
        if (v.checked) {
          this.treeList.forEach((v2, i2) => {
            if (v.parentId.toString().includes(v2.parentId.toString())) {
              v2.show = true
              if (v.parentId.includes(v2.id)) {
                v2.showChild = true
                v2.open = true
              }
            }
          })
        }
      })
    },
    // 点击
    _treeItemTap(item, index) {
      if (item.lastRank === true) {
        // 点击最后一级时触发事件
        this.treeList[index].checked = !this.treeList[index].checked
        this._fixMultiple(index)
        return
      }
      const list = this.treeList
      const id = item.id
      item.showChild = !item.showChild
      item.open = item.showChild ? true : !item.open
      list.forEach((childItem, i) => {
        if (item.showChild === false) {
          // 隐藏所有子级
          if (!childItem.parentId.includes(id))
            return

          if (!this.foldAll) {
            if (childItem.lastRank !== true && !childItem.open)
              childItem.showChild = false

            // 为隐藏的内容添加一个标记
            if (childItem.show)
              childItem.hideArr[item.rank] = id
          }
          else {
            if (childItem.lastRank !== true)
              childItem.showChild = false
          }
          childItem.show = false
        }
        else {
          // 打开子集
          if (childItem.parentId[childItem.parentId.length - 1] === id)
            childItem.show = true

          // 打开被隐藏的子集
          if (childItem.parentId.includes(id) && !this.foldAll) {
            if (childItem.hideArr[item.rank] === id) {
              childItem.show = true
              if (childItem.open && childItem.showChild)
                childItem.showChild = true
              else
                childItem.showChild = false

              childItem.hideArr[item.rank] = null
            }
          }
        }
      })
    },
    _treeItemSelect(item, index) {
      // 选了一个子级，父级自动勾选
      this.treeList.forEach((v) => {
        if (v.id == item.parentId)
          v.checked = true
      })
      // 在选中父级，子级全部选中
      const id = item.id
      item.checked = !item.checked
      const list = this.treeList
      list.forEach((v) => {
        if (v.parentId.includes(id)) {
          v.checked = true
          if (!item.checked)
            v.checked = false
        }
      })
      this._fixMultiple(index)
    },
    _fixMultiple(index) {
      if (!this.multiple) {
        // 如果是单选
        this.treeList.forEach((v, i) => {
          if (i != index)
            this.treeList[i].checked = false
          else
            this.treeList[i].checked = true
        })
      }
    },
    // 重置数据
    _reTreeList() {
      this.treeList.forEach((v, i) => {
        this.treeList[i].checked = v.orChecked
      })
    },
    _initTree(range = this.range) {
      this.treeList = []
      this._renderTreeList(range)
      const ids = storage.getCityID('cityID').split(',')
      // 回显
      this.treeList.forEach((item) => {
        if (ids.includes(item.id))
          item.checked = true
      })
      this.$nextTick(() => {
        this._defaultSelect(range)
      })
    },
  },

}
</script>

<template xlang="wxml">
  <view class="tki-tree">
    <view class="tki-tree-mask" :class="{ show: showTree }" @tap="_cancel" />
    <view class="tki-tree-cnt" :class="{ show: showTree }">
      <view class="tki-tree-bar">
        <view class="tki-tree-bar-cancel" :style="{ color: cancelColor }" hover-class="hover-c" @tap="_cancel">
          取消
        </view>
        <view class="tki-tree-bar-title" :style="{ color: titleColor }">
          {{ title }}
        </view>
        <view class="tki-tree-bar-confirm" :style="{ color: confirmColor }" hover-class="hover-c" @tap="_confirm">
          确定
        </view>
      </view>
      <view class="tki-tree-view">
        <scroll-view class="tki-tree-view-sc" :scroll-y="true">
          <block v-for="(item, index) in treeList" :key="index">
            <view
              v-if="item.show" class="tki-tree-item" :style="[{
                paddingLeft: `${item.rank * 15}px`,
                zIndex: item.rank * -1 + 50,
              }]" :class="{
                border: border === true,
                show: item.show,
                last: item.lastRank,
                showchild: item.showChild,
                open: item.open,
              }"
            >
              <view class="tki-tree-label" @tap.stop="_treeItemTap(item, index)">
                <image class="tki-tree-icon" :src="item.lastRank ? lastIcon : item.showChild ? currentIcon : defaultIcon">
                  {{ item.name }}
                </image>
              </view>
              <view
                v-if="selectParent ? true : item.lastRank" class="tki-tree-check"
                @tap.stop="_treeItemSelect(item, index)"
              >
                <view
                  v-if="item.checked" class="tki-tree-check-yes" :class="{ radio: !multiple }"
                  :style="{ 'border-color': confirmColor }"
                >
                  <view class="tki-tree-check-yes-b" :style="{ 'background-color': confirmColor }" />
                </view>
                <view
                  v-else class="tki-tree-check-no" :class="{ radio: !multiple }"
                  :style="{ 'border-color': confirmColor }"
                />
              </view>
            </view>
          </block>
        </scroll-view>
      </view>
    </view>
  </view>
</template>

<style scoped>
@import "./style.css";
</style>
